/**
 * 递归
 * 递归是把问题分季节为一系列相似的小问题，通过函数不断调用自身来解决这个一个个小问题，直到
 * 满足条件为止，就完成了问题的求解
 * ts 类型系统不支持循环，但支持递归 当处理数量(个数、长度、层数)不固定的类型的时候，可以只处理
 * 一个类型 然后递归的调用自身处理下一个类型 直到结束条件也就是所有的类型都处理完了 就完成了
 * 不确定数量的类型编程 达到循环的效果
 */

// Promise 的递归复用

// DeepPromiseValueType

type ttt1 = Promise<Promise<Record<"peng", 1>>>;
// 这里是3层 promise value 类型
// 数量不确定的话 就需要使用递归来做 每次只处理一层的提取 剩下到下次 直到结束

/**
 * 思路 用infer ValueType 声明一个局部变量 存放进 这个变量当中
 * 如果 ValueType 判断依然是 Promise 类型 然后做递归处理
 * 结束条件就是 ValueType 不为 Promise 类型 那就处理完 所有的层数 返回ValueType
 */
type DeepPromiseValueType<P extends Promise<unknown>> = P extends Promise<
  infer ValueType
>
  ? ValueType extends Promise<unknown>
    ? DeepPromiseValueType<ValueType>
    : ValueType
  : never;

type DeepPromiseValueTypeRes = DeepPromiseValueType<ttt1>;

// 优化 不在 约束为 Promise 类型 就可以少判断一层
type DeepPromiseValueType1<T> = T extends Promise<infer ValueType>
  ? DeepPromiseValueType1<ValueType>
  : T;

type DeepPromiseValue1TypeRes = DeepPromiseValueType1<ttt1>;

// 数组类型的递归

// ReverseArr
type ReverseArr<Arr extends unknown[]> = Arr extends [
  infer One,
  infer Two,
  infer Three
]
  ? [Three, Two, One]
  : never;

type ReverseArrRes = ReverseArr<[1, 2, 3]>;

// Includes

type IsEqual<A, B> = (A extends B ? true : false) &
  (B extends A ? true : false);

type Includes<Arr extends unknown[], FindItem> = Arr extends [
  infer First,
  ...infer Rest
]
  ? IsEqual<First, FindItem> extends true
    ? First
    : Includes<Rest, FindItem>
  : false;

type IncludesRes = Includes<[1, 2, 3, 4], 5>;

// RemoveItem
type RemoveItem<
  Arr extends unknown[],
  Item,
  Result extends unknown[] = []
> = Arr extends [infer First, ...infer Rest]
  ? IsEqual<First, Item> extends true
    ? RemoveItem<Rest, Item, Result>
    : RemoveItem<Rest, Item, [...Result, First]>
  : Result;

type RemoveItemRes = RemoveItem<[1, 2, 2, 3], 4>;

// BuildArray
type BuildArray<
  Length extends number,
  Element = unknown,
  Arr extends unknown[] = []
> = Arr["length"] extends Length
  ? Arr
  : BuildArray<Length, Element, [...Arr, Element]>;

type BuildArrayRes = BuildArray<5>;

// ReplaceAll
type ReplaceStr<
  Str extends string,
  From extends string,
  To extends string
> = Str extends `${infer Prefix}${From}${infer Suffix}`
  ? `${Prefix}${To}${ReplaceStr<Suffix, From, To>}`
  : Str;

type ReplaceStrRes = ReplaceStr<"PenePeng best friend is ? ?", "?", "GaoPeng">;

// StringToUnion
type StringToUnion<Str extends string> =
  Str extends `${infer One}${infer Two}${infer Three}${infer Four}`
    ? One | Two | Three | Four
    : never;

// StringToUnionRes
type StringToUnionRes = StringToUnion<"pengpeng">; // 测试shell

// ReverseString
// 递归提取和构造
type ReverseString<Str extends string> = Str extends `${infer One}${infer Rest}`
  ? `${ReverseString<Rest>}${One}`
  : Str;

type ReverseStringRes = ReverseString<"gaopeng">;

// 对象类型的递归

type ToReadly<T> = {
  readonly [Key in keyof T]: T[Key];
};

type ReadonlyRes = ToReadly<{
  name: string;
  age: number;
}>;

// DeepReadonly
type DeepReadonly<T extends Record<string, any>> = T extends any
  ? {
      readonly [Key in keyof T]: T[Key] extends object
        ? T[Key] extends Function
          ? T[Key]
          : DeepReadonly<T[Key]>
        : T[Key];
    }
  : never;

type DeepReadonlyRes = DeepReadonly<{
  name: string;
  age: number;
  friend: {
    eat: () => void;
    name: string;
    age: number;
  };
}>;
